home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-10-16 | 38.9 KB | 1,559 lines | [TEXT/MPS ] |
- /*------------------------------------------------------------------------------------------
-
- Program: CPlusTESample 2.0AE
- File: TEDocument.cp
- Uses: TEDocument.h
- TESample.h
-
- by Andrew Shebanow
- of Apple Macintosh Developer Technical Support
- with modifications by Eric Berdahl
-
- Copyright © 1989-1990 Apple Computer, Inc.
- Copyright © 1992 Eric Berdahl
- All rights reserved.
-
- ------------------------------------------------------------------------------------------*/
-
- // Mac Includes
- #ifndef __TYPES__
- #include <Types.h>
- #endif
- #ifndef __QUICKDRAW__
- #include <QuickDraw.h>
- #endif
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
- #ifndef __EVENTS__
- #include <Events.h>
- #endif
- #ifndef __CONTROLS__
- #include <Controls.h>
- #endif
- #ifndef __WINDOWS__
- #include <Windows.h>
- #endif
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
- #ifndef __DESK__
- #include <Desk.h>
- #endif
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
- #ifndef __SEGLOAD__
- #include <SegLoad.h>
- #endif
- #ifndef __FILES__
- #include <Files.h>
- #endif
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __AEOBJECTS__
- #include "AEObjects.h"
- #endif
- #ifndef __AEREGISTRY__
- #include "AERegistry.h"
- #endif
- #ifndef __TEDOCUMENT__
- #include "TEDocument.h"
- #endif
- #ifndef __TESAMPLE__
- #include "TESample.h"
- #endif
-
- extern "C" {
- // prototypes for functions that can't belong to TEDocument, but
- // which are closely tied into our documents
- pascal ClikLoopProcPtr GetOldClikLoop();
- pascal void PascalClikLoop();
- void CommonAction(ControlHandle control,short* amount);
- pascal void VActionProc(ControlHandle control,short part);
- pascal void HActionProc(ControlHandle control,short part);
- // this routine is written in Assembler, since it needs to tweak registers
- pascal void ASMCLIKLOOP();
- };
-
- // kTextMargin is the number of pixels we leave blank at the edge of the window.
- const short kTextMargin = 2;
-
- // kMaxDocWidth is an arbitrary number used to specify the width of the TERec's
- // destination rectangle so that word wrap and horizontal scrolling can be
- // demonstrated.
- const short kMaxDocWidth = 576;
-
- // kMinDocDim is used to limit the minimum dimension of a window when GrowWindow
- // is called.
- const short kMinDocDim = 64;
-
- // kMaxTELength is an arbitrary number used to limit the length of text in the TERec
- // so that various errors won't occur from too many characters being in the text.
- const short kMaxTELength = 32000;
-
- // kControlInvisible is used the same way to 'turn on' the control.
- const short kControlVisible = 0xFF;
-
- // ScrollBarAdjust, GrowBoxAdjust, and ScrollBar width are used in calculating
- // values for control positioning and sizing.
- const short kScrollbarAdjust = 15;
- const short kGrowboxAdjust = 15;
- const short kScrollbarWidth = 16;
-
- // kTESlop provides some extra security when pre-flighting edit commands.
- const short kTESlop = 1024;
-
- // kScrollTweek compensates for off-by-one requirements of the scrollbars
- // to have borders coincide with the growbox.
- const short kScrollTweek = 2;
-
- // kCrChar is used to match with a carriage return when calculating the
- // number of lines in the TextEdit record. kDelChar is used to check for
- // delete in keyDowns.
- const short kCrChar = 13;
- const short kDelChar = 8;
-
- //--------------------------------------------------------------------------------
- // TWindowName
- //--------------------------------------------------------------------------------
-
- class TWindowName : public MAppleObject
- {
- public:
- TWindowName(TEDocument* itsDocument);
-
- virtual void DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon);
- virtual DescType GetAppleClass() const;
-
- virtual void DoAppleGetData(const AppleEvent& message, AppleEvent& reply);
- virtual void DoAppleSetData(const AppleEvent& message, AppleEvent& reply);
- private:
- TWindowName();
-
- TEDocument* fDocument;
- };
-
-
- TWindowName::TWindowName(TEDocument* itsDocument)
- {
- fDocument = itsDocument;
- }
-
-
- void TWindowName::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cSetData:
- this->DoAppleSetData(message, reply);
- break;
- case cGetData:
- this->DoAppleGetData(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- DescType TWindowName::GetAppleClass() const
- {
- return typeText;
- }
-
-
- void TWindowName::DoAppleGetData(const AppleEvent& message, AppleEvent& reply)
- {
- MAppleObject::GotRequiredParameters(message);
-
- // Get the name of the window
- Str255 name;
- GetWTitle(fDocument->GetDocWindow(), name);
-
- // Pack the text into a descriptor
- AEDesc nameDesc;
- FailOSErr(AECreateDesc(typeText, (Ptr) &name[1], name[0], &nameDesc));
-
- // package the reply
- OSErr theErr = AEPutParamDesc(&reply, keyDirectObject, &nameDesc);
-
- // dispose of the descriptor we created and check the reply from
- // packaging the reply
- OSErr ignoreErr = AEDisposeDesc(&nameDesc);
- FailOSErr(theErr);
- }
-
-
- void TWindowName::DoAppleSetData(const AppleEvent& message, AppleEvent& /* reply */)
- {
- DescType returnedType;
- Str255 theName;
- Size actualSize;
- FailOSErr(AEGetParamPtr(&message, keyAETheData, typeText, &returnedType,
- (Ptr) &theName[1], 255, &actualSize));
- if (actualSize > 255)
- actualSize = 255;
- theName[0] = (unsigned char) actualSize;
-
- MAppleObject::GotRequiredParameters(message);
-
- SetWTitle(fDocument->GetDocWindow(), theName);
- }
-
-
- //--------------------------------------------------------------------------------
- // TWindowPosition
- //--------------------------------------------------------------------------------
-
- class TWindowPosition : public MAppleObject
- {
- public:
- TWindowPosition(TEDocument* itsDocument);
-
- virtual void DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon);
- virtual DescType GetAppleClass() const;
-
- virtual void DoAppleGetData(const AppleEvent& message, AppleEvent& reply);
- virtual void DoAppleSetData(const AppleEvent& message, AppleEvent& reply);
- private:
- TWindowPosition();
-
- TEDocument* fDocument;
- };
-
-
- TWindowPosition::TWindowPosition(TEDocument* itsDocument)
- {
- fDocument = itsDocument;
- }
-
-
- void TWindowPosition::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cSetData:
- this->DoAppleSetData(message, reply);
- break;
- case cGetData:
- this->DoAppleGetData(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- DescType TWindowPosition::GetAppleClass() const
- {
- return cQDPoint;
- }
-
-
- void TWindowPosition::DoAppleGetData(const AppleEvent& message, AppleEvent& reply)
- {
- MAppleObject::GotRequiredParameters(message);
-
- // Get the position of the window (topLeft of the bounds)
- Rect myBounds = (*WindowPeek(fDocument->GetDocWindow())->strucRgn)->rgnBBox;
- Point myPosition;
- myPosition.v = myBounds.top;
- myPosition.h = myBounds.left;
-
- // Pack the position into a descriptor
- AEDesc posDesc;
- FailOSErr(AECreateDesc(typeQDPoint, (Ptr) &myPosition, sizeof(myPosition), &posDesc));
-
- // package the reply
- OSErr theErr = AEPutParamDesc(&reply, keyDirectObject, &posDesc);
-
- // dispose of the descriptor we created and check the reply from
- // packaging the reply
- OSErr ignoreErr = AEDisposeDesc(&posDesc);
- FailOSErr(theErr);
- }
-
-
- void TWindowPosition::DoAppleSetData(const AppleEvent& message, AppleEvent& /* reply */)
- {
- // Get the new position
- DescType returnedType;
- Point thePos;
- Size actualSize;
- FailOSErr(AEGetParamPtr(&message, keyAETheData, typeQDPoint, &returnedType,
- (Ptr) &thePos, sizeof(thePos), &actualSize));
-
- MAppleObject::GotRequiredParameters(message);
-
- // the point is for the structure region, and is in global coordinates
- // MoveWindow applies to the content region, so we have to massage a little
- // the massage is specific to the type of window we are using
- thePos.v += 19;
- thePos.h++;
-
- // myPoint is now adjusted for the content region
- MoveWindow(fDocument->GetDocWindow(), thePos.h, thePos.v, false);
- }
-
-
- //--------------------------------------------------------------------------------
- // TWindowBounds
- //--------------------------------------------------------------------------------
-
- class TWindowBounds : public MAppleObject
- {
- public:
- TWindowBounds(TEDocument* itsDocument);
-
- virtual void DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon);
- virtual DescType GetAppleClass() const;
-
- virtual void DoAppleGetData(const AppleEvent& message, AppleEvent& reply);
- virtual void DoAppleSetData(const AppleEvent& message, AppleEvent& reply);
- private:
- TWindowBounds();
-
- TEDocument* fDocument;
- };
-
-
- TWindowBounds::TWindowBounds(TEDocument* itsDocument)
- {
- fDocument = itsDocument;
- }
-
-
- void TWindowBounds::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cSetData:
- this->DoAppleSetData(message, reply);
- break;
- case cGetData:
- this->DoAppleGetData(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- DescType TWindowBounds::GetAppleClass() const
- {
- return cQDRectangle;
- }
-
-
- void TWindowBounds::DoAppleGetData(const AppleEvent& message, AppleEvent& reply)
- {
- MAppleObject::GotRequiredParameters(message);
-
- // Get the bounds of the window
- Rect myBounds = (*WindowPeek(fDocument->GetDocWindow())->strucRgn)->rgnBBox;
-
- // Pack the bounds into a descriptor
- AEDesc boundsDesc;
- FailOSErr(AECreateDesc(typeQDRectangle, (Ptr) &myBounds, sizeof(myBounds), &boundsDesc));
-
- // package the reply
- OSErr theErr = AEPutParamDesc(&reply, keyDirectObject, &boundsDesc);
-
- // dispose of the descriptor we created and check the reply from
- // packaging the reply
- OSErr ignoreErr = AEDisposeDesc(&boundsDesc);
- FailOSErr(theErr);
- }
-
-
- void TWindowBounds::DoAppleSetData(const AppleEvent& message, AppleEvent& /* reply */)
- {
- // Get the new bounds
- DescType returnedType;
- Rect theBounds;
- Size actualSize;
- FailOSErr(AEGetParamPtr(&message, keyAETheData, typeQDRectangle, &returnedType,
- (Ptr) &theBounds, sizeof(theBounds), &actualSize));
-
- MAppleObject::GotRequiredParameters(message);
-
- // the rectangle is for the structure region, and is in global coordinates
- // MoveWindow and SizeWindow apply to the content region, so we have to massage a little
- // the massage is specific to the type of window we are using
- theBounds.top += 19;
- theBounds.left++;
- theBounds.bottom -= 2;
- theBounds.right -= 2;
-
- // theBounds is now adjusted for the content region
- MoveWindow(fDocument->GetDocWindow(), theBounds.left, theBounds.top, false);
- SizeWindow(fDocument->GetDocWindow(), theBounds.right - theBounds.left,
- theBounds.bottom - theBounds.top, true);
-
- fDocument->UpdateForNewSelection();
- fDocument->AdjustScrollbars(true);
- }
-
-
- //--------------------------------------------------------------------------------
- // TEditText
- //--------------------------------------------------------------------------------
-
- class TEditText : public MAppleObject
- {
- public:
- TEditText(TEDocument* itsDocument, TEHandle itsTE);
-
- virtual void DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon);
- virtual DescType GetAppleClass() const;
-
- virtual void DoAppleGetData(const AppleEvent& message, AppleEvent& reply);
- virtual void DoAppleSetData(const AppleEvent& message, AppleEvent& reply);
- private:
- TEditText();
-
- TEDocument* fDocument;
- TEHandle fTEHandle;
- };
-
-
- TEditText::TEditText(TEDocument* itsDocument, TEHandle itsTE)
- {
- fDocument = itsDocument;
- fTEHandle = itsTE;
- }
-
-
- void TEditText::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cSetData:
- this->DoAppleSetData(message, reply);
- break;
- case cGetData:
- this->DoAppleGetData(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- DescType TEditText::GetAppleClass() const
- {
- return typeText;
- }
-
-
- void TEditText::DoAppleGetData(const AppleEvent& message, AppleEvent& reply)
- {
- MAppleObject::GotRequiredParameters(message);
-
- // Pack the text into a descriptor
- CharsHandle theText = TEGetText(fTEHandle);
- AEDesc textDesc;
- HLock((Handle) theText);
- OSErr theErr = AECreateDesc(typeText, (Ptr) *theText,
- GetHandleSize((Handle) theText), &textDesc);
-
- // Unlock the handle and check the error code
- HUnlock((Handle) theText);
- FailOSErr(theErr);
-
- // package the reply
- theErr = AEPutParamDesc(&reply, keyDirectObject, &textDesc);
-
- // dispose of the descriptor we created and check the reply from
- // packaging the reply
- OSErr ignoreErr = AEDisposeDesc(&textDesc);
- FailOSErr(theErr);
- }
-
-
- void TEditText::DoAppleSetData(const AppleEvent& message, AppleEvent& /* reply */)
- {
- AEDesc textDesc;
- FailOSErr(AEGetParamDesc(&message, keyAETheData, typeText, &textDesc));
-
- MAppleObject::GotRequiredParameters(message);
-
- HLock(textDesc.dataHandle);
- TESetText(*textDesc.dataHandle, GetHandleSize(textDesc.dataHandle), fTEHandle);
- HUnlock(textDesc.dataHandle);
-
- OSErr ignoreErr = AEDisposeDesc(&textDesc);
-
- HLock((Handle) fTEHandle);
- InvalRect(&(*fTEHandle)->viewRect);
- HUnlock((Handle) fTEHandle);
-
- fDocument->UpdateForNewSelection();
- fDocument->AdjustScrollbars(true);
- }
-
-
- //--------------------------------------------------------------------------------
- // TEDocument
- //--------------------------------------------------------------------------------
-
- // notice that we pass the resID parameter up to our base class,
- // which actually creates the window for us
- TEDocument::TEDocument(short resID) : TDocument(resID, kTEFileType)
- {
- Boolean good;
- Rect destRect, viewRect;
-
- good = false;
- SetPort(fDocWindow);
- GetTERect(&viewRect);
- destRect = viewRect;
- destRect.right = destRect.left + kMaxDocWidth;
- fDocTE = TEStylNew(&destRect, &viewRect);
- FailNIL(fDocTE);
-
- // set up TE record
- AdjustViewRect();
- TEAutoView(true, fDocTE);
- fDocClik = (*fDocTE)->clikLoop;
- (*fDocTE)->clikLoop = (ClikLoopProcPtr) ASMCLIKLOOP;
-
- fDocVScroll = fDocHScroll = nil;
-
- // get vertical scrollbar
- TRY
- {
- fDocVScroll = GetNewControl(rVScroll, fDocWindow);
- FailNILResource(fDocVScroll);
- fDocHScroll = GetNewControl(rHScroll, fDocWindow);
- FailNILResource(fDocHScroll);
- }
- RECOVER
- {
- TEDispose(fDocTE);
- if (fDocVScroll)
- delete fDocVScroll;
- if (fDocHScroll)
- delete fDocHScroll;
- FailNewMessage(eNoWindow,gFailMessage,kTEDocErrStrings);
- }
- ENDTRY
-
- TEDocument::UpdateForNewSelection();
-
- AdjustScrollValues(true);
- ShowWindow(fDocWindow);
- SelectWindow(fDocWindow);
- }
-
- TEDocument::~TEDocument()
- {
- HideWindow(fDocWindow);
- if ( fDocTE != nil )
- {
- TEDispose(fDocTE); // dispose the TEHandle if we got far enough to make one
- }
- if ( fDocVScroll != nil )
- {
- DisposeControl(fDocVScroll);
- }
- if ( fDocHScroll != nil )
- {
- DisposeControl(fDocHScroll);
- }
- // base class destructor will dispose of window
- }
-
- void TEDocument::DoZoom(short partCode)
- {
- Rect tRect;
-
- tRect = fDocWindow->portRect;
- EraseRect(&tRect);
- ZoomWindow(fDocWindow, partCode, fDocWindow == FrontWindow());
- AdjustScrollbars(true); // adjust, redraw anyway
- AdjustTE();
- InvalRect(&tRect); // invalidate the whole content
- // the scrollbars were taken care of by AdjustScrollbars, so validate ’em
- tRect = (*fDocVScroll)->contrlRect;
- ValidRect(&tRect);
- tRect = (*fDocHScroll)->contrlRect;
- ValidRect(&tRect);
- }
-
- // Called when a mouseDown occurs in the grow box of an active window.
-
- void TEDocument::DoGrow(EventRecord* theEvent)
- {
- long growResult;
- Rect tRect, tRect2;
-
- tRect = qd.screenBits.bounds;
- tRect.left = kMinDocDim;
- tRect.top = kMinDocDim;
- growResult = GrowWindow(fDocWindow, theEvent->where, &tRect);
- // see if it really changed size
- if ( growResult != 0 )
- {
- tRect = (*fDocTE)->viewRect;
- SizeWindow(fDocWindow, LoWord(growResult), HiWord(growResult), true);
- AdjustScrollbars(true);
- AdjustTE();
- // calculate & validate the region that hasn’t changed so it won’t get redrawn
- // Note: we copy rectangles so that we don't take address of object fields.
- tRect2 = (*fDocTE)->viewRect;
- (void) SectRect(&tRect, &tRect2, &tRect);
- tRect2 = fDocWindow->portRect; InvalRect(&tRect2);
- ValidRect(&tRect);
- tRect2 = (*fDocVScroll)->contrlRect; ValidRect(&tRect2);
- tRect2 = (*fDocHScroll)->contrlRect; ValidRect(&tRect2);
- }
- }
-
- void TEDocument::DoContent(EventRecord* theEvent)
- {
- Point mouse;
- ControlHandle control;
- short part, value;
- Boolean shiftDown;
- Rect teRect;
-
- SetPort(fDocWindow);
- mouse = theEvent->where; // get the click position
- GlobalToLocal(&mouse);
- GetTERect(&teRect);
- if ( PtInRect(mouse, &teRect) )
- {
- // see if we need to extend the selection
- shiftDown = (theEvent->modifiers & shiftKey) != 0; // extend if Shift is down
- TEClick(mouse, shiftDown, fDocTE);
- UpdateForNewSelection();
- }
- else
- {
- part = FindControl(mouse, fDocWindow, &control);
- switch ( part )
- {
- case 0:
- // do nothing if not in a control
- break;
- case inThumb:
- value = GetCtlValue(control);
- part = TrackControl(control, mouse, nil);
- if ( part != 0 )
- {
- value -= GetCtlValue(control);
- // value now has CHANGE in value; if value changed, scroll
- if ( value != 0 )
- if ( control == fDocVScroll )
- TEScroll(0, value * (*fDocTE)->lineHeight, fDocTE);
- else TEScroll(value, 0, fDocTE);
- }
- break;
- default: // they clicked in an arrow, so track & scroll
- if ( control == fDocVScroll )
- value = TrackControl(control, mouse, (ProcPtr) VActionProc);
- else value = TrackControl(control, mouse, (ProcPtr) HActionProc);
- break;
- }
- }
- }
-
- void TEDocument::DoKeyDown(EventRecord* theEvent)
- {
- char key;
-
- if (theEvent->modifiers & cmdKey) // don't process command characters
- return;
- key = (char) (theEvent->message & charCodeMask);
- // we have a char. for our window; see if we are still below TextEdit’s
- // limit for the number of characters
- if ((key != kDelChar) &&
- ((*fDocTE)->teLength - ((*fDocTE)->selEnd - (*fDocTE)->selStart) + 1 >= kMaxTELength) )
- Failure(eExceedChar,kTEDocErrStrings);
-
- TEKey(key, fDocTE);
- UpdateForNewSelection();
- AdjustScrollbars(false);
- AdjustTE();
- fDirty = true;
- }
-
- void TEDocument::DoActivate(Boolean becomingActive)
- {
- if ( becomingActive )
- {
- RgnHandle tempRgn;
- RgnHandle clipRgn;
- Rect growRect;
- Rect tRect;
-
- // since we don’t want TEActivate to draw a selection in an area where
- // we’re going to erase and redraw, we’ll clip out the update region
- // before calling it.
- tempRgn = NewRgn();
- clipRgn = NewRgn();
- // save old update region
- CopyRgn(((WindowPeek) fDocWindow)->updateRgn, tempRgn);
- // put it in local coords
- OffsetRgn(tempRgn, fDocWindow->portBits.bounds.left, fDocWindow->portBits.bounds.top);
- GetClip(clipRgn);
- // subtract updateRgn from clipRgn
- DiffRgn(clipRgn, tempRgn, tempRgn);
- // make it the new clipRgn
- SetClip(tempRgn);
- TEActivate(fDocTE);
- // restore the full-blown clipRgn
- SetClip(clipRgn);
- // get rid of temp regions
- DisposeRgn(tempRgn);
- DisposeRgn(clipRgn);
-
- // the controls must be redrawn on activation:
- (*fDocVScroll)->contrlVis = kControlVisible;
- (*fDocHScroll)->contrlVis = kControlVisible;
- // copy rectangles to avoid unsafe object field references!
- tRect = (*fDocVScroll)->contrlRect; InvalRect(&tRect);
- tRect = (*fDocHScroll)->contrlRect; InvalRect(&tRect);
- // the growbox needs to be redrawn on activation:
- growRect = fDocWindow->portRect;
- // adjust for the scrollbars
- growRect.top = growRect.bottom - kScrollbarAdjust;
- growRect.left = growRect.right - kScrollbarAdjust;
- InvalRect(&growRect);
- }
- else
- {
- TEDeactivate(fDocTE);
- // the controls must be hidden on deactivation:
- HideControl(fDocVScroll);
- HideControl(fDocHScroll);
- // we draw grow icon immediately, since we deactivate controls
- // immediately, and the update delay looks funny
- DrawGrowIcon(fDocWindow);
- }
- }
-
- void TEDocument::DoUpdate()
- {
- BeginUpdate(fDocWindow); // this sets up the visRgn
- if ( ! EmptyRgn(fDocWindow->visRgn) ) // draw if updating needs to be done
- {
- DrawWindow();
- }
- EndUpdate(fDocWindow);
- }
-
- // calculate how much idle time we need
-
- unsigned long TEDocument::CalcIdle()
- {
- if (HaveSelection())
- return GetCaretTime();
- else return kMaxSleepTime; // if we don't have a selection, we don't need to idle
- }
-
- // This is called whenever we get a null event et al.
- // It takes care of necessary periodic actions. For this program,
- // it calls TEIdle.
-
- void TEDocument::DoIdle()
- {
- TEIdle(fDocTE);
- } // DoIdle
-
- // Draw the contents of an application window.
-
- void TEDocument::DrawWindow()
- {
- Rect tRect;
-
- SetPort(fDocWindow);
- tRect = fDocWindow->portRect;
- EraseRect(&tRect);
- TEUpdate(&tRect, fDocTE);
- DrawControls(fDocWindow);
- DrawGrowIcon(fDocWindow);
- } // DrawWindow
-
- // Return a rectangle that is inset from the portRect by the size of
- // the scrollbars and a little extra margin.
-
- void TEDocument::GetTERect(Rect* teRect)
- {
- *teRect = fDocWindow->portRect;
- InsetRect(teRect, kTextMargin, kTextMargin); // adjust for margin
- teRect->bottom = teRect->bottom - kScrollbarAdjust; // and for the scrollbars
- teRect->right = teRect->right - kScrollbarAdjust;
- } // GetTERect
-
- // setup a region which contains the visible text
-
- void TEDocument::GetVisTERgn(RgnHandle rgn)
- {
- Rect teRect;
-
- teRect = (*fDocTE)->viewRect; // get a local copy of viewRect
- SetPort(fDocWindow); // make sure we have right port
- LocalToGlobal((Point*) &teRect.top);
- LocalToGlobal((Point*) &teRect.bottom);
- RectRgn(rgn, &teRect);
- // we temporarily change the port’s origin to “globalfy” the visRgn
- SetOrigin(-(fDocWindow->portBits.bounds.left),
- -(fDocWindow->portBits.bounds.top));
- SectRgn(rgn, fDocWindow->visRgn, rgn);
- SetOrigin(0, 0);
- } // GetTERgn
-
- void TEDocument::ReadFromFile(short refNum)
- {
- long curPos, size;
- Handle h;
-
- // determine how much data is available to read
- FailOSErr(GetFPos(refNum,&curPos));
- FailOSErr(GetEOF(refNum,&size));
- size -= curPos;
-
- // check for size > 32K
- if (size > kMaxTELength)
- Failure(eExceedChar,kTEDocErrStrings);
-
- // allocate a handle to store it in
- h = NewHandle(size);
- FailNIL(h);
-
- TRY
- {
- FailOSErr(FSRead(refNum,&size,*h));
- }
- RECOVER
- {
- DisposHandle(h);
- }
- ENDTRY
-
- // now make the text the current text
- SetPort(fDocWindow);
- HLock(h);
- TESetText(*h,size,fDocTE);
- DisposHandle(h);
-
- // make sure everything is up to date
- Rect tRect = (*fDocTE)->viewRect;
- InvalRect(&tRect);
- AdjustTE();
- UpdateForNewSelection();
- AdjustScrollbars(false);
- }
-
- void TEDocument::WriteToFile(short refNum)
- {
- Handle h;
- long size;
-
- // get COPY of TEHandle - doesn't alloc memory
- h = (Handle) TEGetText(fDocTE);
- size = GetHandleSize(h);
- FailOSErr(FSWrite(refNum,&size,*h));
- }
-
- // Return boolean value indicating that there is or is not a
- // selection in the document
-
- Boolean TEDocument::HaveSelection()
- {
- if ( (*fDocTE)->selStart < (*fDocTE)->selEnd )
- return true;
- else return false;
- }
-
- // Update the TERec's view rect so that it is the greatest multiple of
- // the lineHeight that still fits in the old viewRect.
-
- void TEDocument::AdjustViewRect()
- {
- TEPtr te;
-
- te = *fDocTE;
- te->viewRect.bottom = (((te->viewRect.bottom - te->viewRect.top) / te->lineHeight)
- * te->lineHeight) + te->viewRect.top;
- } // AdjustViewRect
-
- // Scroll the TERec around to match up to the potentially updated scrollbar
- // values. This is really useful when the window has been resized such that the
- // scrollbars became inactive but the TERec was already scrolled.
-
- void TEDocument::AdjustTE()
- {
- TEPtr te;
-
- te = *fDocTE;
- TEScroll((te->viewRect.left - te->destRect.left) - GetCtlValue(fDocHScroll),
- (te->viewRect.top - te->destRect.top) -
- (GetCtlValue(fDocVScroll) * te->lineHeight),
- fDocTE);
- } // AdjustTE
-
- // Re-calculate the position and size of the viewRect and the scrollbars.
- // kScrollTweek compensates for off-by-one requirements of the scrollbars
- // to have borders coincide with the growbox.
-
- void TEDocument::AdjustScrollSizes()
- {
- Rect teRect;
-
- GetTERect(&teRect);
- (*fDocTE)->viewRect = teRect;
- AdjustViewRect();
- MoveControl(fDocVScroll, fDocWindow->portRect.right - kScrollbarAdjust, -1);
- SizeControl(fDocVScroll, kScrollbarWidth,
- fDocWindow->portRect.bottom - fDocWindow->portRect.top -
- kGrowboxAdjust + kScrollTweek);
- MoveControl(fDocHScroll, -1, fDocWindow->portRect.bottom - kScrollbarAdjust);
- SizeControl(fDocHScroll,
- fDocWindow->portRect.right - fDocWindow->portRect.left -
- kGrowboxAdjust + kScrollTweek,
- kScrollbarWidth);
- } // AdjustScrollSizes
-
- // Turn off the controls by jamming a zero into their contrlVis fields (HideControl erases them
- // and we don't want that). If the controls are to be resized as well, call the procedure to do that,
- // then call the procedure to adjust the maximum and current values. Finally re-enable the controls
- // by jamming a $FF in their contrlVis fields (ShowControl re-draws the control, which may not be
- // necessary).
-
- void TEDocument::AdjustScrollbars(Boolean needsResize)
- {
- // First, turn visibility of scrollbars off so we won’t get unwanted redrawing
- (*fDocVScroll)->contrlVis = 0;
- (*fDocHScroll)->contrlVis = 0;
- if ( needsResize )
- AdjustScrollSizes();
- AdjustScrollValues(needsResize);
- // Now, restore visibility in case we never had to draw during adjustment
- (*fDocVScroll)->contrlVis = 0xff;
- (*fDocHScroll)->contrlVis = 0xff;
- } // AdjustScrollbars
-
- // Calculate the new control maximum value and current value, whether it is the horizontal or
- // vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
- // vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
- // width to the width of the viewRect. The current values are set by comparing the offset between
- // the view and destination rects. If necessary, redraw the control by calling ShowControl.
-
- void TEDocument::AdjustHV(Boolean isVert,Boolean mustRedraw)
- {
- short value, lines, max;
- short oldValue, oldMax;
- TEPtr te;
- ControlHandle control;
-
- if (isVert)
- control = fDocVScroll;
- else control = fDocHScroll;
- oldValue = GetCtlValue(control);
- oldMax = GetCtlMax(control);
- te = *fDocTE; // point to TERec for convenience
- if ( isVert )
- {
- lines = te->nLines;
- // since nLines isn’t right if the last character is a return, check for that case
- if ( *(*te->hText + te->teLength - 1) == kCrChar )
- lines += 1;
- max = lines - ((te->viewRect.bottom - te->viewRect.top) /
- te->lineHeight);
- }
- else max = kMaxDocWidth - (te->viewRect.right - te->viewRect.left);
-
- if ( max < 0 )
- max = 0;
- SetCtlMax(control, max);
-
- // Must deref. after SetCtlMax since, technically, it could draw and therefore move
- // memory. This is why we don’t just do it once at the beginning.
- te = *fDocTE;
- if ( isVert )
- value = (te->viewRect.top - te->destRect.top) / te->lineHeight;
- else value = te->viewRect.left - te->destRect.left;
-
- if ( value < 0 )
- value = 0;
- else if ( value > max )
- value = max;
-
- SetCtlValue(control, value);
- // now redraw the control if asked to or if a setting changed
- if ( mustRedraw || (max != oldMax) || (value != oldValue) )
- ShowControl(control);
- } // AdjustHV
-
- // Simply call the common adjust routine for the vertical and horizontal scrollbars.
-
- void TEDocument::AdjustScrollValues(Boolean mustRedraw)
- {
- AdjustHV(true, mustRedraw);
- AdjustHV(false, mustRedraw);
- } // AdjustScrollValues
-
- ClikLoopProcPtr TEDocument::GetClikLoop()
- {
- return fDocClik;
- }
-
- TEHandle TEDocument::GetTEHandle()
- {
- return fDocTE;
- }
-
- void TEDocument::DoCut()
- {
- long total, contig;
-
- if (ZeroScrap() == noErr)
- {
- PurgeSpace(&total, &contig);
- if ((*fDocTE)->selEnd - (*fDocTE)->selStart + kTESlop > contig)
- Failure(eNoSpaceCut,kTEDocErrStrings);
-
- TECut(fDocTE);
- fDirty = true;
- if (TEToScrap() != noErr)
- {
- (void) ZeroScrap();
- Failure(eNoCut,kTEDocErrStrings);
- }
- }
- UpdateForNewSelection();
- AdjustScrollbars(false);
- AdjustTE();
- }
-
- void TEDocument::DoCopy()
- {
- if (ZeroScrap() == noErr)
- {
- TECopy(fDocTE); // after copying, export the TE scrap
- if (TEToScrap() != noErr)
- {
- ZeroScrap();
- Failure(eNoCopy,kTEDocErrStrings);
- }
- }
- UpdateForNewSelection();
- AdjustScrollbars(false);
- AdjustTE();
- }
-
- void TEDocument::DoPaste()
- {
- Handle aHandle;
- long oldSize, newSize;
- OSErr saveErr;
-
- if ( TEGetScrapLen() + ((*fDocTE)->teLength -
- ((*fDocTE)->selEnd - (*fDocTE)->selStart)) > kMaxTELength )
- Failure(eExceedPaste,kTEDocErrStrings);
-
- aHandle = (Handle) TEGetText(fDocTE);
- oldSize = GetHandleSize(aHandle);
- newSize = oldSize + TEGetScrapLen() + kTESlop;
-
- // preflight the growth of the text handle for textedit,
- // since it will crash if it doesn't have enough memory
- SetHandleSize(aHandle, newSize);
- saveErr = MemError();
- SetHandleSize(aHandle, oldSize);
- if (saveErr != noErr)
- Failure(eNoSpacePaste,kTEDocErrStrings);
-
- TEStylPaste(fDocTE);
- fDirty = true;
-
- UpdateForNewSelection();
- AdjustScrollbars(false);
- AdjustTE();
- }
-
- void TEDocument::DoClear()
- {
- TEDelete(fDocTE);
- fDirty = true;
- UpdateForNewSelection();
- AdjustScrollbars(false);
- AdjustTE();
- }
-
- void TEDocument::DoSelectAll()
- {
- long selSize = (*fDocTE)->teLength;
- TESetSelect(0,selSize,fDocTE);
- UpdateForNewSelection();
- }
-
-
- void TEDocument::SetFontName(Str255 fontName)
- {
- short fontID;
-
- GetFNum(fontName, &fontID);
- SetFont(fontID);
- }
-
- void TEDocument::SetFont(short fontID)
- {
- fTxStyle.tsFont = fontID;
- TESetStyle(doFont, &fTxStyle, true, fDocTE);
- fDirty = true;
- UpdateForNewSelection();
- AdjustScrollbars(false);
- }
-
- void TEDocument::SetFontSize(short fontSize)
- {
- fTxStyle.tsSize = fontSize;
- TESetStyle(doSize, &fTxStyle, true, fDocTE);
- fDirty = true;
- UpdateForNewSelection();
- AdjustScrollbars(false);
- }
-
- short TEDocument::GetSelectionFontSize()
- {
- return (fSelSizeContinuous ? fTxStyle.tsSize : -1);
- }
-
- short TEDocument::GetSelectionFont()
- {
- return (fSelFontContinuous ? fTxStyle.tsFont : -1);
- }
-
- void TEDocument::SetFaceAttributes(short attributes, Boolean on)
- {
- if (on)
- fTxStyle.tsFace |= attributes;
- else
- fTxStyle.tsFace &= ~attributes;
-
- TESetStyle(doFace, &fTxStyle, true, fDocTE);
- fDirty = true;
- UpdateForNewSelection();
- AdjustScrollbars(false);
- }
-
- void TEDocument::SetPlain()
- {
- fTxStyle.tsFace = normal;
-
- TESetStyle(doFace, &fTxStyle, true, fDocTE);
- fDirty = true;
- UpdateForNewSelection();
- AdjustScrollbars(false);
- }
-
- void TEDocument::SetUnderline(Boolean on)
- {
- SetFaceAttributes(underline, on);
- }
-
- void TEDocument::SetOutline(Boolean on)
- {
- SetFaceAttributes(outline, on);
- }
-
- void TEDocument::SetShadow(Boolean on)
- {
- SetFaceAttributes(shadow, on);
- }
-
- void TEDocument::SetItalic(Boolean on)
- {
- SetFaceAttributes(italic, on);
- }
-
- void TEDocument::SetBold(Boolean on)
- {
- SetFaceAttributes(bold, on);
- }
-
- Boolean TEDocument::GetFaceAttributes(short attributes)
- {
- return (fSelFaceContinuous && (fTxStyle.tsFace & attributes) == attributes);
- }
-
- Boolean TEDocument::SelectionIsPlain()
- {
- return (fSelFaceContinuous && fTxStyle.tsFace == normal);
- }
-
- Boolean TEDocument::SelectionIsUnderline()
- {
- return GetFaceAttributes(underline);
- }
-
- Boolean TEDocument::SelectionIsOutline()
- {
- return GetFaceAttributes(outline);
- }
-
- Boolean TEDocument::SelectionIsShadow()
- {
- return GetFaceAttributes(shadow);
- }
-
- Boolean TEDocument::SelectionIsItalic()
- {
- return GetFaceAttributes(italic);
- }
-
- Boolean TEDocument::SelectionIsBold()
- {
- return GetFaceAttributes(bold);
- }
-
- void TEDocument::UpdateForNewSelection()
- {
- // make sure we catch all the text attributes
- short mode = doAll;
- fSelFontContinuous = TEContinuousStyle(&mode, &fTxStyle, fDocTE);
-
- // then, ask for each type in which we are interested individually
- mode = doFont;
- fSelFontContinuous = TEContinuousStyle(&mode, &fTxStyle, fDocTE);
-
- mode = doFace;
- fSelFaceContinuous = TEContinuousStyle(&mode, &fTxStyle, fDocTE);
-
- mode = doSize;
- fSelSizeContinuous = TEContinuousStyle(&mode, &fTxStyle, fDocTE);
- }
-
-
- /*
- Routines used by this class, which don't belong to the class since we use
- them as toolbox filter routines, and you cannot pass class methods as ProcPtrs.
- */
-
- // Common algorithm for pinning the value of a control. It returns the actual amount
- // the value of the control changed.
-
- void CommonAction(ControlHandle control,short* amount)
- {
- short value, max;
-
- value = GetCtlValue(control);
- max = GetCtlMax(control);
- *amount = value - *amount;
- if ( *amount <= 0 )
- *amount = 0;
- else if ( *amount >= max )
- *amount = max;
- SetCtlValue(control, *amount);
- *amount = value - *amount;
- } // CommonAction
-
-
- // Determines how much to change the value of the vertical scrollbar by and how
- // much to scroll the TE record.
-
- pascal void TEDocument::VActionProc(ControlHandle control,short part)
- {
- short amount;
- WindowPtr window;
- TEPtr te;
- TEDocument* doc;
-
- if ( part != 0 )
- {
- window = (*control)->contrlOwner;
- doc = (TEDocument*) (TESample::GetTEApplication()->DocList())->FindDoc(window);
- te = *(doc->GetTEHandle());
- switch ( part )
- {
- case inUpButton:
- case inDownButton: // one line
- amount = 1;
- break;
- case inPageUp: // one page
- case inPageDown:
- amount = (te->viewRect.bottom - te->viewRect.top) / te->lineHeight;
- break;
- }
- if ( (part == inDownButton) || (part == inPageDown) )
- amount = -amount; // reverse direction for a downer
- CommonAction(control, &amount);
- if ( amount != 0 )
- TEScroll(0, amount * te->lineHeight, doc->GetTEHandle());
- }
- } // VActionProc
-
- // Determines how much to change the value of the horizontal scrollbar by and how
- // much to scroll the TE record.
-
- pascal void TEDocument::HActionProc(ControlHandle control,short part)
- {
- short amount;
- WindowPtr window;
- TEPtr te;
- TEDocument* doc;
-
- if ( part != 0 )
- {
- window = (*control)->contrlOwner;
- doc = (TEDocument*) (TESample::GetTEApplication()->DocList())->FindDoc(window);
- te = *(doc->GetTEHandle());
- switch ( part )
- {
- case inUpButton:
- case inDownButton: // a few pixels
- amount = 4;
- break;
- case inPageUp: // a page
- case inPageDown:
- amount = te->viewRect.right - te->viewRect.left;
- break;
- }
- if ( (part == inDownButton) || (part == inPageDown) )
- amount = -amount; // reverse direction
- CommonAction(control, &amount);
- if ( amount != 0 )
- TEScroll(amount, 0, doc->GetTEHandle());
- }
- } // VActionProc
-
- // Gets called from our assembly language routine, AsmClikLoop, which is in
- // turn called by the TEClick toolbox routine. Saves the windows clip region,
- // sets it to the portRect, adjusts the scrollbar values to match the TE scroll
- // amount, then restores the clip region.
-
- pascal void PascalClikLoop()
- {
- RgnHandle region;
- WindowPtr wind;
- TEDocument* doc;
-
- wind = FrontWindow();
- doc = (TEDocument*) (TESample::GetTEApplication()->DocList())->FindDoc(wind);
- region = NewRgn();
- GetClip(region); // save clip
- ClipRect(&wind->portRect);
- doc->AdjustScrollValues(false);
- SetClip(region); // restore clip
- DisposeRgn(region);
- } // PascalClikLoop
-
- // Gets called from our assembly language routine, AsmClikLoop, which is in
- // turn called by the TEClick toolbox routine. It returns the address of the
- // default clikLoop routine that was put into the TERec by TEAutoView to
- // AsmClikLoop so that it can call it.
-
- pascal ClikLoopProcPtr GetOldClikLoop()
- {
- TEDocument* doc;
-
- doc = (TEDocument*) (TESample::GetTEApplication()->DocList())->FindDoc(FrontWindow());
- if (doc == nil)
- return nil;
- return doc->GetClikLoop();
- } // GetOldClikLoop
-
-
-
- DescType TEDocument::GetAppleClass() const
- {
- return cWindow;
- }
-
-
- long TEDocument::CountContainedObjects(DescType ofType)
- {
- return MAppleObject::CountContainedObjects(ofType);
- }
-
-
- void TEDocument::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cSave:
- this->DoAppleSave(message, reply);
- break;
- case cClose:
- this->DoAppleClose(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- MAppleObject* TEDocument::GetContainedObject(DescType desiredType, DescType keyForm,
- const AEDesc& keyData, Boolean& needDisposal)
- {
- MAppleObject* result = nil;
-
- switch (keyForm)
- {
- case formPropertyID:
- result = this->GetAppleProperty(keyForm, keyData, needDisposal);
- break;
- }
-
- if (result == nil)
- result = MAppleObject::GetContainedObject(desiredType, keyForm, keyData, needDisposal);
-
- return result;
- }
-
-
- MAppleObject* TEDocument::GetAppleProperty(DescType keyForm, const AEDesc& keyData,
- Boolean& needDisposal)
- {
- MAppleObject* result = nil;
-
- // Our property accessors only work on formPropertyID
- if (keyForm != formPropertyID)
- FailOSErr(errAEWrongDataType);
-
- DescType whichProperty;
- if (keyData.descriptorType == typeType)
- whichProperty = *(DescType*)*keyData.dataHandle;
- else
- {
- AEDesc whichPropertyDesc;
- FailOSErr(AECoerceDesc(&keyData, typeType, &whichPropertyDesc));
- whichProperty = *(DescType*)*whichPropertyDesc.dataHandle;
- OSErr ignoreErr = AEDisposeDesc(&whichPropertyDesc);
- }
-
- switch (whichProperty)
- {
- case pBounds:
- result = new TWindowBounds(this);
- FailNIL(result);
- needDisposal = true;
- break;
- case pPosition:
- result = new TWindowPosition(this);
- FailNIL(result);
- needDisposal = true;
- break;
- case pName:
- result = new TWindowName(this);
- FailNIL(result);
- needDisposal = true;
- break;
- case pText:
- result = new TEditText(this, fDocTE);
- FailNIL(result);
- needDisposal = true;
- break;
- }
-
- return result;
- }
-
-
- Boolean TEDocument::CompareAppleObjects(DescType operation, const MAppleObject& toWhat)
- {
- return MAppleObject::CompareAppleObjects(operation, toWhat);
- }
-
-
- void TEDocument::DoAppleSave(const AppleEvent& message, AppleEvent& /* reply */)
- {
- DescType returnedType;
- Size actualSize;
- FSSpec myFSSpec;
-
- OSErr tempErr = AEGetParamPtr(&message, keyAEDestination,
- typeFSS, &returnedType, (Ptr) &myFSSpec,
- sizeof(myFSSpec), &actualSize);
- if (tempErr == noErr)
- {
- MAppleObject::GotRequiredParameters(message);
- this->CloseFile();
- fFile = myFSSpec;
- this->OpenFile(false, true);
- this->DoSave();
- }
- else if (tempErr != errAEDescNotFound)
- FailOSErr(tempErr);
- else
- MAppleObject::GotRequiredParameters(message);
- }
-
-
-
- void TEDocument::DoAppleClose(const AppleEvent& message, AppleEvent& /* reply */)
- {
- DescType saveOpt = kAEYes; // default to save on close
-
- DescType returnedType;
- Size actualSize;
- OSErr tempErr = AEGetParamPtr(&message, keyAESaveOptions,
- cEnumeration, &returnedType,
- (Ptr) &saveOpt,
- sizeof(saveOpt), &actualSize);
- if (tempErr != noErr && tempErr != errAEDescNotFound)
- FailOSErr(tempErr);
-
- if (saveOpt == kAEYes)
- {
- FSSpec myFSSpec;
- tempErr = AEGetParamPtr(&message, keyAEDestination, typeFSS,
- &returnedType, (Ptr) &myFSSpec, sizeof(myFSSpec),
- &actualSize);
- if (tempErr == noErr)
- {
- MAppleObject::GotRequiredParameters(message);
- this->CloseFile();
- fFile = myFSSpec;
- this->OpenFile(false, true);
- this->DoSave();
- }
- else if (tempErr != errAEDescNotFound)
- FailOSErr(tempErr);
- else
- MAppleObject::GotRequiredParameters(message);
- }
-
- (void) this->DoClose(false, yesResult, false);
-
- TApplication::GetApplication()->DocList()->RemoveDoc(this);
-
- // We really want ourselves deleted now, but it’s really bad form to delete oneself.
- // However, this method gets invoked from an AppleEvent, thus we are a token object
- // and can now set our “disposal flag” to true.
- TAppleObjectDispatcher::GetDispatcher()->SetTokenObjectDisposal(this, true);
- }
-